@node More Pre-Scheme packages
@section More Pre-Scheme packages

Along with the @code{prescheme} structure, there are several other
structures built-in to Pre-Scheme.

@menu

* Pre-Scheme floating point operation::
* Pre-Scheme record types::
* Multiple return values in Pre-Scheme::
* Low-level Pre-Scheme memory manipulation::

@end menu

@node Pre-Scheme floating point operation
@subsection Floating point operation

@stindex ps-flonums
Since Pre-Scheme's strict static type system would not permit
overloading of the arithmetic operators for integers & floats, it
provides a different set of operators for floats.  These names are all
exported by the @code{ps-flonums} structure.

@deffn procedure fl+ augend addend @dots{} @returns{} float
@deffnx procedure fl- float @returns{} float
@deffnx procedure fl- minuend subtrahend @returns{} float
@deffnx procedure fl* multiplier multiplicand @dots{} @returns{} float
@deffnx procedure fl/ divisor dividend @returns{} float
@deffnx procedure fl= float@suba{a} float@suba{b} @returns{} boolean
@deffnx procedure fl< float@suba{a} float@suba{b} @returns{} boolean
@deffnx procedure fl> float@suba{a} float@suba{b} @returns{} boolean
@deffnx procedure fl<= float@suba{a} float@suba{b} @returns{} boolean
@deffnx procedure fl>= float@suba{a} float@suba{b} @returns{} boolean
All of these operations @code{fl@var{op}} correspond as floating point
variations of their @var{op} integer equivalents.
@end deffn

@node Pre-Scheme record types
@subsection Record types

@stindex ps-record-types
The @code{ps-record-types} structure defines the following special form
for introducing record types.  Pre-Scheme record types are translated
to C as structs.

@deffn syntax define-record-type
@lisp
(define-record-type @var{type} @var{type-descriptor}
  (@var{constructor} @var{argument-field-tag} @dots{})
  (@var{field-tag@sub{1}} @var{field-type-spec@sub{1}}
    @var{field-accessor@sub{1}} [@var{field-modifier@sub{1}}])
  (@var{field-tag@sub{2}} @var{field-type-spec@sub{2}}
    @var{field-accessor@sub{2}} [@var{field-modifier@sub{2}}])
  @dots{}
  (@var{field-tag@sub{n}} @var{field-type-spec@sub{n}}
    @var{field-accessor@sub{n}} [@var{field-modifier@sub{n}}])@end lisp
Defines a record type.  @var{Type} is mangled to the C struct type name
(@var{type-descriptor-name} is unused unless running Pre-Scheme as
Scheme).  @var{Constructor} is defined to construct a record of the new
type and initialize the fields @var{argument-type-field} @dots{} with
its arguments, respectively.  If it cannot allocate a sufficient
quantity of memory, @var{constructor} returns a null pointer.  The
initial values of fields that are not passed to the constructor are
undefined.  For each field @var{field@suba{i}} specified,

@itemize @bullet
@item @var{field@suba{i}} is specified to have the type
@var{field-type-spec@suba{i}};

@item @var{field-accessor@suba{i}} is defined to be a procedure of one
argument, a record of type @var{type-name}, that returns the value of
the field @var{field@suba{i}} of that record --- its type is defined to
be @code{(=> (@var{type-name}) @var{field-type-spec@suba{i}})}; and

@item if present, @var{field-modifier@suba{i}} is defined to be a
procedure of two arguments, a record of type @var{type-name} and a
value of type @var{field-type-spec}, that assigns the value of the
field @var{field@suba{i}} in its first argument to be the value of its
second argument; its type is @code{(=> (@var{type-name}
@var{field-type-spec}) unit)}.
@end itemize

Records must be deallocated explicitly when their lifetime has expired
with @code{deallocate}.
@end deffn

@node Multiple return values in Pre-Scheme
@subsection Multiple return values

@stindex ps-receive
Pre-Scheme support multiple return values, like in Scheme.  The only
difference is that one cannot operate on multiple return values as
lists, since Pre-Scheme does not have lists.  Multiple return values
are implemented in C as returning in C the first value and passing
pointers to the remaining values, which the function returning multiple
values assigns.  The @code{prescheme} structure exports the two
multiple return value primitives, @code{call-with-values} and
@code{values}, but the @code{ps-receive} structure exports this macro
for more conveniently binding multiple return values.

@deffn syntax receive formals producer body
Binds the @code{lambda} parameter list @var{formals} to the multiple
values that @var{producer} returns, and evaluates @var{body} with the
new variables bound.

@lisp
(receive @var{formals}
         @var{producer}
  @var{body})
    @equiv{}
(call-with-values
    (lambda () @var{producer})
  (lambda @var{formals}
    @var{body}))@end lisp
@end deffn

@node Low-level Pre-Scheme memory manipulation
@subsection Low-level memory manipulation

@cindex Pre-Scheme memory management
@cindex memory management in Pre-Scheme
@stindex ps-memory
Pre-Scheme is a low-level language.  It provides very low-level, direct
memory manipulation.  `Addresses' index a flat store of sequences of
bytes.  While Pre-Scheme `pointers' are statically checked for data
coherency, allow no arbitrary arithmetic, and in general are high-level
abstract data to some extent, addresses are much lower-level, have no
statically checked coherency --- the values an address represents are
selected by what operation used to read or write from it ---, permit
arbitrary address arithmetic, and are a much more concrete interface
into direct memory.  The @code{ps-memory} structure exports these
direct memory manipulation primitives.

@deffn procedure allocate-memory size @returns{} address
@deffnx procedure deallocate-memory address @returns{} unit
@code{Allocate-memory} reserves a sequence of @var{size} bytes in the
store and returns an address to the first byte in the sequence.
@code{Deallocate-memory} releases the memory at @var{address}, which
should have been the initial address of a contiguous byte sequence, as
@code{allocate-memory} would return, not an offset address from such an
initial address.
@end deffn

@deffn procedure unsigned-byte-ref address @returns{} unsigned-byte
@deffnx procedure unsigned-byte-set! address unsigned-byte @returns{} unit
@deffnx procedure word-ref address @returns{} word
@deffnx procedure word-set! address word @returns{} unit
@deffnx procedure flonum-ref address @returns{} float
@deffnx procedure flonum-set! address float @returns{} unit
Procedures for reading from & storing to memory.
@code{Unsigned-byte-ref} & @code{unsigned-byte-set!} access & store the
first unsigned byte at @var{address}.  @code{Word-ref} &
@code{word-set!} access & store the first word --- Pre-Scheme integer
--- beginning at @var{address}.  @code{Flonum-ref} & @code{flonum-set!}
access & store 64-bit floats beginning at @var{address}..

@strong{Bug:} @code{Flonum-ref} & @code{flonum-set!} are unimplemented
in the Pre-Scheme-as-Scheme layer (@pxref{Running Pre-Scheme as
Scheme}).
@end deffn

@deffn procedure address? value @returns{} boolean
Disjoint type predicate for addresses.

@strong{Note:} @code{Address?} is available @emph{only} at the top
level, where code is evaluated at compile-time.  Do not use this in any
place where it may be called at run-time.
@end deffn

@defvr constant null-address @returns{} address
The null address.  This is somewhat similar to the null pointer, except
that it is an address.

@strong{Note:} One acquires the null @emph{pointer} by calling the
@emph{procedure} @code{null-pointer}, whereas the constant value of the
@emph{binding} named @code{null-address} is the null @emph{address}.
@end defvr

@deffn procedure null-address? address @returns{} boolean
@code{Null-address?} returns true if @var{address} is the null
address and false if not.
@end deffn

@deffn procedure address+ address increment @returns{} address
@deffnx procedure address- address decrement @returns{} address
@deffnx procedure address-difference address@suba{a} address@suba{b} @returns{} integer
Address arithmetic operators.  @code{Address+} adds @var{increment} to
@var{address}; @code{address-} subtracts @var{decrement} from
@var{address}; and @code{address-difference} returns the integer
difference between @var{address@suba{a}} and @var{address@suba{b}}.
For any @var{address@suba{p}} & @var{address@suba{q}}, @code{(address+
@var{address@suba{p}} (address-difference @var{address@suba{p}}
@var{address@suba{q}}))} is equal to @var{address@suba{q}}.
@end deffn

@deffn procedure address= address@suba{a} address@suba{b} @returns{} boolean
@deffnx procedure address< address@suba{a} address@suba{b} @returns{} boolean
@deffnx procedure address> address@suba{a} address@suba{b} @returns{} boolean
@deffnx procedure address<= address@suba{a} address@suba{b} @returns{} boolean
@deffnx procedure address>= address@suba{a} address@suba{b} @returns{} boolean
Address comparators.
@end deffn

@deffn procedure integer->address integer @returns{} address
@deffnx procedure address->integer address @returns{} integer
Integers and addresses, although not the same type, may be converted to
and from each other; @code{integer->address} & @code{address->integer}
perform this conversion.  Note that Pre-Scheme @emph{pointers} may not
be converted to addresses or integers, and the converse is also true.
@end deffn

@deffn procedure copy-memory! source-address target-address count @returns{} unit
Copies @var{count} bytes starting at @var{source-address} to
@var{target-address}.  This is similar to C's @code{memcpy}.
@end deffn

@deffn procedure memory-equal? address@suba{a} address@suba{b} count @returns{} boolean
Compares the two sequences of @var{count} bytes starting at addresses
@var{address@suba{a}} & @var{address@suba{b}}.  It returns true if every
byte is equal and false if not.
@end deffn

@deffn procedure char-pointer->string address size @returns{} string
@deffnx procedure char-pointer->nul-terminated-string address @returns{} string
@code{Char-pointer->string} returns a string with @var{size} bytes from
the contiguous sequence of bytes starting at @var{address}.
@code{Char-pointer->nul-terminated-string} does similarly, but it
returns a string whose contents include every byte starting at
@var{address} until, but not including, the first 0 byte, @ie{} ASCII
nul character, following @var{address}.
@end deffn

@deffn procedure read-block port address count @returns{} [count-read eof? status]
@deffnx procedure write-block port address count @returns{} status
@code{Read-block} attempts to read @var{count} bytes from @var{port}
into memory starting at @var{address}.  @code{Write-block} attempts to
write @var{count} bytes to @var{port} from the contiguous sequence in
memory starting at @var{address}.  @code{Read-block} returns three
values: the number of bytes read, whether or not the read went to the
end of the file, and the error status (@pxref{Pre-Scheme error
handling}).  @code{Write-block} returns the error status.
@end deffn
